package com.ybw.order.demo.service.impl;

import com.ybw.order.demo.service.RedisService;
import com.ybw.order.demo.utils.GsonUtils;
import com.ybw.order.demo.utils.MapUtils;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @program: redis-distributed-lock
 * @description:
 * @author: geoffrey
 * @create: 2022-02-17 23:23
 */
@Service
@Slf4j
public class RedisServiceImpl implements RedisService {

    @Resource
    private RedissonClient redissonClient;
    private static final long DEFAULT_EXPIRE_UNUSED = 60000L;
    /**
     * @methodName:
     * @param null
     * @return:
     * @author: ybwei
     * @date: 2022/9/4
     **/
    @Resource
    private RedisTemplate redisTemplate;

    @SuppressWarnings("AlibabaLockShouldWithTryFinally")
    @Override
    public RLock lock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        return lock;
    }

    @Override
    public boolean tryLock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        return lock.tryLock();
    }

    @Override
    public boolean tryLock(String lockKey, long timeout) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(timeout, timeout, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            return false;
        }
    }

    @Override
    public void unlock(String lockKey) {
        RLock lock = redissonClient.getLock(lockKey);
        unlock(lock);
    }

    @Override
    public void unlock(RLock lock) {
        if(isHeldByCurrentThread(lock)){
            lock.unlock();
        }
    }

    @Override
    public boolean isHeldByCurrentThread(RLock lock) {
        return lock.isHeldByCurrentThread();
    }

    @Override
    public <T> boolean hmSetObject(String key, T t, Long time, TimeUnit timeUnit) {
        try {
            Map<Object, Object> map = MapUtils.beanToMap(t);
            log.info("map:{}", GsonUtils.toJsonString(map));
            redisTemplate.opsForHash().putAll(key, map);
            if (time > 0) {
                redisTemplate.expire(key, time, timeUnit);
            }
            return true;
        } catch (Exception e) {
            log.error("RedisServiceImpl hmSetObject error:", e);
            return false;
        }
    }

    @Override
    public <T> T hmget(String key,Class<T> clazz) {
        Map<Object, Object> map = redisTemplate.opsForHash().entries(key);
        if (map == null || map.isEmpty()) {
            return null;
        }
        return GsonUtils.strToJavaBean(GsonUtils.toJsonString(map), clazz);
    }
}
